package com.tuozixuan.handler;

import static com.tuozixuan.constant.GitConstants.PASSWORD;
import static com.tuozixuan.constant.GitConstants.USERNAME;

import java.io.File;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PullResult;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.tuozixuan.base.Branch;
import com.tuozixuan.base.Version;
import com.tuozixuan.config.Config;
import com.tuozixuan.constant.OperateEnum;
import com.tuozixuan.util.GitUtils;
import com.tuozixuan.util.MvnUtils;
import com.tuozixuan.util.ProjectUtils;

public class ReleaseHandler implements Handler {
	
	private static Logger logger = LoggerFactory.getLogger(ReleaseHandler.class);

	@Override
	public void execute(Config config) throws Exception {
		
		if (StringUtils.isBlank(config.getMemo())) {
			throw new IllegalArgumentException("memo配置不能為空");
		}
		
		String mavenHome = System.getenv("MAVEN_HOME");
		if (StringUtils.isBlank(mavenHome)) {
			logger.error("MAVEN_HOME环境变量未设置！");
			return;
		}
		logger.info("MAVEN_HOME:{}", mavenHome);
		
		String mvnCmd = StringUtils.appendIfMissing(mavenHome, File.separator) + "bin" + File.separator + "mvn.cmd";
		logger.info("mvnCmd:{}", mvnCmd);
		
		CredentialsProvider credentialsProvider = new UsernamePasswordCredentialsProvider(USERNAME, PASSWORD);
		Map<String, String> projectMap = config.getProjects();
		Map<String, String> resultMap = new LinkedHashMap<>();
		for (Map.Entry<String, String> entry : projectMap.entrySet()) {	
			String projectName = entry.getKey();
			String targetBranch = entry.getValue();
			
			String projectPath = config.getBasePath() + File.separator + projectName;
			logger.info("{} projectPath:{}", projectName, projectPath);
			
			File projectWorkPath = new File(projectPath);
			Git git = Git.open(projectWorkPath);
			Status status = git.status().call();
			if (!status.isClean()) {
				logger.error("{} 存在未提交的文件。status:{}", projectName, status);
				return;
			}
			
			PullResult pullResult = git.pull().setCredentialsProvider(credentialsProvider).call();
			logger.info("{} pullResult:{}", projectName, pullResult);
			if (!pullResult.isSuccessful()) {
				logger.error("{} pull失败", projectName);
				return;
			}
			
			String currentBranchName = git.getRepository().getBranch();
			logger.info("{} currentBranchName:{}", projectName, currentBranchName);
			if (!StringUtils.equals(currentBranchName, targetBranch)) {
				logger.info("当前分支({})与目标分支({})不一致，即将切换到目标分支", currentBranchName, targetBranch);
				git.checkout().setName(targetBranch).call();
				currentBranchName = git.getRepository().getBranch();
				logger.info("已经切换到{}分支", currentBranchName);
			}
			
			List<String> modifyPomFileList = ProjectUtils.getRelativePathNameListByFileName(projectPath, "pom.xml", "/");
			logger.info("{} modifyPomFileList:{}", modifyPomFileList);
			
			String localVersion = MvnUtils.getVersion(mvnCmd, projectWorkPath);
			logger.info("{} localVersion:{}", projectName, localVersion);
			
			Version newLocalVersion = Version.of(localVersion).revisionIncrement();
			logger.info("{} newLocalVersion:{}", projectName, newLocalVersion);
			
			Version releaseVersion = Version.of(localVersion).type(null);
			Branch releaseBranch = Branch.of(releaseVersion.toString()).type("release");
			logger.info("{} releaseBranch:{} releaseVersion:{}", projectName, releaseBranch, releaseVersion);
			
			git.branchCreate().setName(releaseBranch.toString()).call();
			git.checkout().setName(releaseBranch.toString()).call();
			logger.info("{} 创建并切换到本地分支：{}", projectName, releaseBranch);
			
			MvnUtils.changeVersion(mvnCmd, projectWorkPath, releaseVersion);
			MvnUtils.changeDependencyVersion(mvnCmd, projectWorkPath, releaseVersion);
			logger.info("{} 改变版本号{}完成", projectName, releaseVersion);
			
			GitUtils.addFilepatternList(git, modifyPomFileList);
			
			String message = "[new Release " + releaseBranch +"]" + config.getMemo();
			GitUtils.commitAndPush(git, message, credentialsProvider);
			logger.info("{} push新的分支{}完成", projectName, releaseBranch);
			
			git.checkout().setName(currentBranchName).call();
			logger.info("{} 切换到本地分支：{}", projectName, currentBranchName);
			MvnUtils.changeVersion(mvnCmd, projectWorkPath, newLocalVersion);
			MvnUtils.changeDependencyVersion(mvnCmd, projectWorkPath, newLocalVersion);
			logger.info("{} 改变版本号{}完成", projectName, newLocalVersion);
			GitUtils.addFilepatternList(git, modifyPomFileList);
			
			message = "Upgrade snapshot version to " + newLocalVersion;
			GitUtils.commitAndPush(git, message, credentialsProvider);
			logger.info("{} push完成", projectName);
			
			resultMap.put(projectName, releaseBranch.toString());
		}
		
		resultMap.entrySet().stream().forEach(entry -> System.out.println(entry.getKey() + ": " + entry.getValue()));
	}

	@Override
	public OperateEnum getOperate() {
		return OperateEnum.RELEASE;
	}
}
